package scala.test_implicit

/**
 * @author 黄海峰 2021/4/19 16:03
 * */
object DeanTest {

  implicit val stringMonoid: Monoid[String] = new Monoid[String] {
    def add(x: String, y: String): String = x concat y

    def unit: String = ""
  }

  implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
    def add(x: Int, y: Int): Int = x + y

    def unit: Int = 0
  }

  def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
    if (xs.isEmpty) m.unit
    else m.add(xs.head, sum(xs.tail));

  /**
   * List(1, 2, 3) <= List(4, 5) 隐式转换
   */
  import scala.language.implicitConversions

  implicit def list2ordered[A](x: List[A])
                              (implicit elem2ordered: A => Ordered[A]): Ordered[List[A]] =
    new Ordered[List[A]] {
      //replace with a more useful implementation
      def compare(that: List[A]): Int = 1
    }

  def main(args: Array[String]): Unit = {
    println(sum(List(1, 2, 3)))       // uses IntMonoid implicitly
    println(sum(List("a", "b", "c")))   // uses StringMonoid implicitly

    List(1, 2, 3) <= List(4, 5)
  }
}

/**
 * Scala 将查找这些参数的位置分为两类：
 *    scala 在调用包含有隐式参数块的方法时，将首先查找可以直接访问的隐式定义和隐式参数 (无前缀)。
 *    然后，它在所有伴生对象中查找与隐式候选类型相关的有隐式标记的成员。
 *
 *
 */
